﻿#region Copyright Jonathan Quiros

//	
// All rights are reserved. Reproduction or transmission in whole or in 
// part, in any form or by any means, electronic, mechanical or otherwise, 
// is prohibited without the prior written consent of the copyright owner.
//
// Filename: GamesController.cs
//

#endregion

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using Novagoal.Logic;
using Novagoal.Models;
using Novagoal.Website.Models.Forms;
using Novagoal.Website.Models.Views;
using Novagoal.Website.WebApp.Helpers;
using Novagoal.Website.WebApp.Routing;

namespace Novagoal.Website.WebApp.Controllers
{
    public class GamesController : ListController
    {
        #region PROPERTIES

        private readonly GamesLogic _gamesLogic;
        private readonly TournamentsLogic _tournamentsLogic;
        private readonly TeamsLogic _teamsLogic;
        private readonly PlayersLogic _playersLogic;

        #endregion

        #region PUBLIC METHODS

        public GamesController(UsersLogic usersLogic, GamesLogic gamesLogic, 
            TournamentsLogic tournamentsLogic, TeamsLogic teamsLogic, PlayersLogic playersLogic)
            : base(usersLogic)
        {
            _gamesLogic = gamesLogic;
            _tournamentsLogic = tournamentsLogic;
            _teamsLogic = teamsLogic;
            _playersLogic = playersLogic;
        }

        [HttpGet]
        public ActionResult MostValuablePlayer(int gameId)
        {
            var currentUser = GetUserInformation();
            var game = _gamesLogic.GetGame(gameId);
            var mvpViewModel = new MvpViewModel
            {
                TeamA = _teamsLogic.GetTeam(game.TeamA.Id),
                TeamB = _teamsLogic.GetTeam(game.TeamB.Id),
                TeamAPlayers = _gamesLogic.GetTeamPlayers(game.TeamA.Id),
                TeamBPlayers = _gamesLogic.GetTeamPlayers(game.TeamB.Id),
                GameId = gameId
            };
            return PartialView("MostValuablePlayer"+currentUser.Person.Language, mvpViewModel);
        }

        [HttpGet]
        public ActionResult Index()
        {
            var games = _gamesLogic.GetGames(Request.Params, SortField, SortDirection, PageNumber, PageSize);

            var indexViewModel = new IndexViewModel
            {
                List = games,
                RouteValues = games.GetRouteValues(PageSize),
            };
            return View(indexViewModel);
        }

        [HttpPost]
        public ActionResult Index(FormCollection collection)
        {
            return Redirect(collection);
        }

        [HttpGet]
        public ActionResult Add()
        {
            var model = new GamesViewModel
                            {
                                Game = new Game{StartedAt = DateTime.UtcNow},
                                Tournaments = _tournamentsLogic.GetEnabledTournaments(),
                                Teams = new List<Team>()
                            };
            return View("Details", model);
        }

        [HttpGet]
        public ActionResult Edit(int id)
        {
            var game = _gamesLogic.GetGame(id);
            var teams = new List<Team>();
            if(game == null)
            {
                TempData.SetMessage("The game is invalid", MessageType.Warning);
            }
            else
            {
                teams = _teamsLogic.GetTeamsByTournament(game.Tournament.Id);
            }
            var model = new GamesViewModel
            {
                Game = game ?? new Game(),
                Tournaments = _tournamentsLogic.GetEnabledTournaments(),
                Teams = teams
            };
            return View("Details", model);
        }

        [HttpPost]
        public ActionResult Save(GameFormModel formModel)
        {
            var modelView = ModelViewFromForm(formModel);
            if (ModelState.IsValid)
            {
                modelView.Game.Id = _gamesLogic.Save(modelView.Game);
                modelView.SuccessMessage = "Game saved successfully";
            }

            return View("Details", modelView);
        }

        [HttpGet]
        public ActionResult Close(int id)
        {
            var model = new GamesViewModel
                            {
                                Game = _gamesLogic.GetGame(id)
                            };
            return View(model);
        }

        [HttpPost]
        public ActionResult ClosePreview(ResultsFormModel resultsFormModel)
        {
            var currentUser = GetUserInformation();
            var game = CreateGames(resultsFormModel).FirstOrDefault();
            var model = new GamesCloseViewModel
                            {
                                Results = game != null
                                              ? _gamesLogic.CalculateResults(game)
                                              : new Dictionary<Person, Result>()
                            };
            return PartialView("Results"+currentUser.Person.Language, model);
        }

        [HttpPost]
        public ActionResult Close(ResultsFormModel resultsFormModel)
        {
            var game = CreateGames(resultsFormModel).FirstOrDefault();
            var viewModel = new GamesViewModel{Game = game};
            if(ModelState.IsValid)
            {
                _gamesLogic.CloseGame(game);
                _playersLogic.UpdateMvp(game.PredictedResult.Player.Id);
                // ReSharper disable Asp.NotResolved
                return RedirectToAction("Index");
                // ReSharper restore Asp.NotResolved
            }
            return View(viewModel);
        }

        [HttpPost]
        public ActionResult UpdateResults(ResultsFormModel form)
        {
            var message = string.Empty;
            var status = true;
            try
            {
                var games = CreateGames(form);
                _gamesLogic.SaveResults(games);
            }
            catch (Exception exception)
            {
                message = exception.ToString();
                status = false;
            }
            return Json(new { Status = status, Messages = message }, JsonRequestBehavior.AllowGet);
        }

        [HttpGet]
        public ActionResult Results(int gameId)
        {
            var currentUser = GetUserInformation();
            var model = new GamesCloseViewModel
                            {
                                Results = _gamesLogic.GetResults(gameId),
                            };

            return PartialView("Results"+currentUser.Person.Language, model);
        }

        [HttpGet]
        public ActionResult ResultsPreview(int id)
        {
            var currentUser = GetUserInformation();
            var model = new GamesCloseViewModel
            {
                Results = _gamesLogic.GetResults(id),
            };

            return PartialView("ResultsPreview" + currentUser.Person.Language, model);
        }

        public ActionResult History(int id)
        {
            var currentUser = GetUserInformation();
            var gameList = _gamesLogic.GetGames(id);
            return PartialView("History"+currentUser.Person.Language,gameList);
        }

        #endregion

        #region PRIVATE METHODS

        private GamesViewModel ModelViewFromForm(GameFormModel formModel)
        {
            var provider = CultureInfo.InvariantCulture;
            return new GamesViewModel
                       {
                           Tournaments = _tournamentsLogic.GetEnabledTournaments(),
                           Teams = _teamsLogic.GetTeamsByTournament(formModel.TournamentId),
                           Game = new Game
                                      {
                                          Id = formModel.GameId,
                                          TeamA = new Team{Id = formModel.TeamAId},
                                          TeamB = new Team{Id = formModel.TeamBId},
                                          Tournament = new Tournament{Id = formModel.TournamentId},
                                          StartedAt = DateTime.ParseExact(formModel.StartAt, "MM/dd/yyyy HH:mm", provider),
                                          UpdatedBy = SecurityContext.User.Id,
                                      }
                       };
        }

        private IEnumerable<Game> CreateGames(ResultsFormModel form)
        {
            var user = GetUserInformation();

            return form.GameId.Select((gameId, i) => new Game
            {
                Id = gameId,
                PredictedResult = new Result
                {
                    TeamAScore = form.TeamA[i],
                    TeamBScore = form.TeamB[i],
                    UpdatedBy = user.Person.Id,
                    Player = new Player { Id = form.Mvp[i] }
                }
            }).ToList();
        }

        #endregion
    }
}
